package org.linlinjava.litemall.wx.web;



import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;


import com.alibaba.fastjson.JSON;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;


import com.alipay.api.internal.util.AlipaySignature;

import com.alipay.api.internal.util.AlipaySignature;

import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;



import org.linlinjava.litemall.core.config.AlipayConfig;

import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.domain.LitemallOrder;

import org.linlinjava.litemall.db.service.LitemallMoneyLogService;
import org.linlinjava.litemall.db.service.LitemallOrderService;
import org.linlinjava.litemall.db.util.OrderHandleOption;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.linlinjava.litemall.wx.annotation.LoginUser;
import org.linlinjava.litemall.wx.dto.AlipayNotifyParam;
import org.linlinjava.litemall.wx.service.WxOrderService;

import org.linlinjava.litemall.wx.service.XiaofeiquanPay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static org.linlinjava.litemall.wx.util.WxResponseCode.AUTH_OPENID_UNACCESS;
import static org.linlinjava.litemall.wx.util.WxResponseCode.ORDER_INVALID_OPERATION;

@RestController
@RequestMapping("/wx/order")
@Validated
public class WxOrderController {



    @Autowired
    private WxOrderService wxOrderService;

    /*注入收支服务*/
    @Autowired
    LitemallMoneyLogService litemallMoneyLogService;

    @Autowired
    private LitemallOrderService orderService;

@Autowired
private XiaofeiquanPay  xiaofeiquanPay;

    private static Logger logger = LoggerFactory.getLogger(WxOrderController.class);

    private ExecutorService executorService = Executors.newFixedThreadPool(20);


    @GetMapping("/test")
    public Object Test() {
        return wxOrderService.Test();
    }

    /**
     * 订单列表
     *
     * @param userId   用户ID
     * @param showType 显示类型，如果是0则是全部订单
     * @param page     分页页数
     * @param limit    分页大小
     * @param sort     排序字段
     * @param order    排序方式
     * @return 订单列表
     */
    @GetMapping("list")
    public Object list(@LoginUser Integer userId,
                       @RequestParam(defaultValue = "0") Integer showType,
                       @RequestParam(defaultValue = "1") Integer page,
                       @RequestParam(defaultValue = "10") Integer limit,
                       @Sort @RequestParam(defaultValue = "add_time") String sort,
                       @Order @RequestParam(defaultValue = "desc") String order) {
        return wxOrderService.list(userId, showType, page, limit, sort, order);
    }

    /**
     * 订单详情
     * @param userId  用户ID
     * @param orderId 订单ID
     * @return 订单详情
     */
    @GetMapping("detail")
    public Object detail(@LoginUser Integer userId, @NotNull Integer orderId) {
        return wxOrderService.detail(userId, orderId);
    }

    /**
     * 提交订单
     *
     * @param userId 用户ID
     * @param body   订单信息，{ cartId：xxx, addressId: xxx, couponId: xxx, message: xxx, grouponRulesId: xxx,  grouponLinkId: xxx}
     * @return 提交订单操作结果
     */
    @PostMapping("submit")
    public Object submit(@LoginUser Integer userId, @RequestBody String body) {
        logger.info("userId========" + userId);
        logger.info("body============" + body);
        return wxOrderService.submit(userId, body);
    }

    /**
     * 取消订单
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 取消订单操作结果
     */
    @PostMapping("cancel")
    public Object cancel(@LoginUser Integer userId, @RequestBody String body) {
        return wxOrderService.cancel(userId, body);
    }


    /**
     * 付款订单的预支付会话标识
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 支付订单ID
     */
    @PostMapping("prepay")
    public Object prepay(@LoginUser Integer userId, @RequestBody String body, HttpServletRequest request) {


        return wxOrderService.prepay(userId, body, request);
    }



    /**
     * 支付宝支付
     *
     * @param userId
     * @param body
     * @return
     */
    @PostMapping("zfbprepay")
    public Object zfbprepay(@LoginUser Integer userId, @RequestBody String body) {


        //获取到订单信息
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");

        if (orderId == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findByIdTest(userId, orderId);

        if (order == null) {
            return ResponseUtil.badArgumentValue();
        }

        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.badArgumentValue();
        }

        // 检测是否能够取消
        OrderHandleOption handleOption = OrderUtil.build(order);
        if (!handleOption.isPay()) {
            return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能支付");
        }



        if (!orderId.equals(null)){


            System.out.println(order);



/** 支付宝网关 **/
            String URL = "https://openapi.alipay.com/gateway.do";

/** 应用id，如何获取请参考：https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/
            String APP_ID = "2021003137662206";

/** 应用私钥，如何获取请参考：https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/
            String APP_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCT7vsQP+BOTnt+aY4J9IAOt1kXjoK7tR60aFlx3Pj4VnTjXrwFXg7pGlz4ek6N+z+1bWn8zmrhmNwWAOjuJWNmBOi+68hJvn7wQN+rW7lSuPdhFtU2t4/uFme6RDabeTjlLxPqmo8hMwe+0GZD0U51xzql8oEsPzifdiPHIW7xIex9D9T92ZLxlEOV+15/nKQTiKtwmvX785YBQmvX3+yXyXzhTlRI434OFg2J2uqszw2UpehZW399HmM2r5L8ZX/jLSfHm2Rajl2VGOnYalsHTJdMbr1hH16HzJ169P1x5c5Eo/Fuw9fSDP6w2pKWNoRUEOoCukOVcGagu4khPWWZAgMBAAECggEAcZNtVlB0WiqPTcKktqftGV9TG27imFK6PDBRW8YXsDJQk7BMEqLgN79x2aOtY/yeMSDL2rhv/rxpXMteCljSM6VZPBuyLkv/EV39W4aUhhpUc0ogcF4GNvkksjFk64DqWasHU3tOoGKZc7p0iWTNJEfNk1LYMaxoQKVnWp8kmiQR1ap7A2MuTL+ecbVvD3qHjBZ7StJQoZVaIXlIRYc+dld/i//6fY/xue0mymy9zB0wxjBPu4kVYopTbp/ObRAcUqbzU2JJtLfZ6NHZ0YXf+xoVGqGpusKnXuoia8SEEF/2+H8C3dpKN4uqTSZKB6scRVqy9vNkRTamLvSFCQB+AQKBgQDRjGqEfF6JHCh5fUGuWvyK0F2llqdTP4nWMmrFMrvuPLz8Ml5iydnlLX3yePFTkK9boYhkbJFuT2NgReqnsCGJgmAlerYKa6EZ1Pwky5OMm9NU/flRZLPhhueVbufyppwd4RICigRtNdRMpBYv7wTHmG7vrsTVoiLmbegTboeaSQKBgQC0ugAuD86XtBiY3B6bTHHn8ArukBFpnDUFMRoRqJ+GyIJJbpF63DbNHBt4YRlqNdpk5wqZYEd867ZM30qPsSJlXElYiaL1pZKQxuk0zYHU6C0qBg4Dvn0aDA9VzM3kh2p1RA5YKrW6lPJKap/rfF6CtXN+YTIKNIjOyZNFhMTw0QKBgBHmKpsSfIi9rP9joZ6hCv1YewdP7Q8BWGbBe7lIciERcxsfukw57bDTx/RUPFjk/PWYwKvDUlDX2yc4EaktNFAooMnSx4XwV5x7QuZptTrHfK+/2fIH5g2XlmR/SrTBYohy1zT8URB7Dp1VTsfdZM0fyioTBaEx7kU8khxGzrJxAoGAMutpG5FGkwWiHIeAdB8QxNmkKt0amtfxNFpGTw1kjRQ3aTsm8CfVpOqzbrJk98DenKlgGiC/Y5oCDhynpF6zIz3iSHjXGkEhT3tLv53bY8Ja30k/b5yfINSfCXyf0jC5NPsM05iNBVnr/j2We0HaWxeGx+fYsnlkxmaTAPZMitECgYEApVg0uZ1mw/qkP5A/Xg21yw4OZMnroCPLHdFqG4z0edjYB7KYPy9xB2RcjxlcMiH/IyPggMvHtN/3J7HYAYvB9Dv6g2DMzU0zi7fJg0fSJ3vwEnnxT2IpWpDXn2b0fVXH4Zpe2If7qXq4VHsUvVSUtDYE3kdKQigNyg/gXVyVZjI=";

/** 支付宝公钥，如何获取请参考：https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/
            String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk+77ED/gTk57fmmOCfSADrdZF46Cu7UetGhZcdz4+FZ04168BV4O6Rpc+HpOjfs/tW1p/M5q4ZjcFgDo7iVjZgTovuvISb5+8EDfq1u5Urj3YRbVNreP7hZnukQ2m3k45S8T6pqPITMHvtBmQ9FOdcc6pfKBLD84n3YjxyFu8SHsfQ/U/dmS8ZRDlftef5ykE4ircJr1+/OWAUJr19/sl8l84U5USON+DhYNidrqrM8NlKXoWVt/fR5jNq+S/GV/4y0nx5tkWo5dlRjp2GpbB0yXTG69YR9eh8ydevT9ceXORKPxbsPX0gz+sNqSljaEVBDqArpDlXBmoLuJIT1lmQIDAQAB";

/** 初始化 **/
            AlipayClient alipayClient = new DefaultAlipayClient(URL,APP_ID,APP_PRIVATE_KEY,"json","UTF-8",ALIPAY_PUBLIC_KEY,"RSA2");

/** 实例化具体API对应的request类，类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay（app 支付接口）**/
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

/** 设置业务参数 **/
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();


            /**
             * 这里可以给请求设置商品详情信息可以存放商品list
             */
            // model.setGoodsDetail(null);


            /**
             * 获取订单编号
             */
            String orderSn = order.getOrderSn();

/** 商户订单号，商户自定义，需保证在商户端不重复，如：20200612000001 **/
            model.setOutTradeNo(orderSn);

/** 订单标题 **/
            model.setSubject("订单标题");

/** 销售产品码，固定值：QUICK_MSECURITY_PAY **/
            model.setProductCode("QUICK_MSECURITY_PAY");

            BigDecimal actualPrice = order.getActualPrice();

            //这里要把实付价格改为字符串

            String payPrice = actualPrice.toString();


/** 订单金额，精确到小数点后两位 **/
            model.setTotalAmount(payPrice);

            Integer payUser = order.getUserId();
            String merchantUserId = payUser.toString();

/** 订单描述 **/
            model.setBody("益品荟-付款用户[" + merchantUserId + "]");

/** 业务扩展参数 **/
//ExtendParams extendParams = new ExtendParams();

/** 花呗分期参数传值前提：必须有该接口花呗收款准入条件，且需签约花呗分期 **/
/** 指定可选期数，只支持3/6/12期，还款期数越长手续费越高 **/
// extendParams.setHbFqNum("3");

/** 指定花呗分期手续费承担方式，手续费可以由用户全承担（该值为0），也可以商户全承担（该值为100），但不可以共同承担，即不可取0和100外的其他值。 **/
//extendParams.setHbFqSellerPercent("0");

//model.setExtendParams(extendParams);

/** 将业务参数传至request中 **/
            request.setBizModel(model);

/** 异步通知地址，以http或者https开头的，商户外网可以post访问的异步地址，用于接收支付宝返回的支付结果，如果未收到该通知可参考该文档进行确认：https://opensupport.alipay.com/support/helpcenter/193/201602475759 **/
            request.setNotifyUrl("http://api.skypshop.com/wx/order/zfbpay");

/**第三方调用（服务商模式），传值app_auth_token后，会收款至授权token对应商家账号，如何获传值app_auth_token请参考文档：https://opensupport.alipay.com/support/helpcenter/79/201602494631 **/
//request.putOtherTextParam("app_auth_token", "传入获取到的app_auth_token值");

            AlipayTradeAppPayResponse response = null;
            try {

/** 通过alipayClient调用API，获得对应的response类 **/
                response = alipayClient.sdkExecute(request);

            } catch (AlipayApiException e) {

                e.printStackTrace();
            }

/** response.getBody()打印结果就是orderString，可以直接给客户端请求，无需再做处理。 如果传值客户端失败，可根据返回错误信息到该文档寻找排查方案：https://opensupport.alipay.com/support/helpcenter/89 **/
            System.out.println("-----------"+response.getBody()+"--------------------");




            return ResponseUtil.ok(response.getBody());

        }else {

            return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单已经失效");

        }

    }






    /**
     * <pre>
     * 第一步:验证签名,签名通过后进行第二步
     * 第二步:按一下步骤进行验证
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
     * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
     * 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
     * </pre>
     *
     */
    //检查支付状态接口
    @PostMapping("zfbpay")
    public Object zfbpay(HttpServletRequest request ) {


        //编码格式
        String charset="utf-8";
        //支付宝公钥
        String alipaypublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoTAdSr2AAjJpW723wKzfCjj1dhwSgOoES5kUz501QcfaQ4vz4CyxSCXVy3fq+odl1Hs2OImDEmhwGp/6P40I8gyn7GNraxi9QIbPa2NDpbZqXdPDHVgYeqz8ax/YthTMHjV+oHugS7YPpskyYDLVqE0APaRCkTLiERUszidlMGJC2YaT5wlTgdXBnGwvwscVt9sdETEVFa1chr7xj2bz89DFIEyJmlkCMDVLZE9Me1Y0VFKrC3z5Jn1yMdADOSc3Y8genMvJ3n1OOy7bLPcrj1vgG4cdZmQWMgnqRxCauQWkN2nFLZvJXdf+AWb/VRe2wX9JW9m4YZ9rOXhK7CMDxwIDAQAB";
        //签名方式
        String sign_type="RSA2";

        Map<String, String> paramss = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
        AlipayNotifyParam param = buildAlipayNotifyParam(paramss);
        logger.info("###############传给业务方法的对象"+param+"###############");





        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();

        Map requestParams = request.getParameterMap();

        logger.info("##############转化前的params"+requestParams+"###############");

        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        logger.info("##############转化后的params"+requestParams+"################");

        try {
//异步验签：切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
//公钥证书模式验签，alipayPublicCertPath是支付宝公钥证书引用路径地址，需在对应应用中下载
//boolean signVerified= AlipaySignature.rsaCertCheckV1(params, alipayPublicCertPath, charset,sign_type);
//普通公钥模式验签，切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
/* 实际验证过程建议商户务必添加以下校验：
    1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
    2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
    3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
    4、验证app_id是否为该商户本身。
    */

            //验签方法
            boolean signVerified = false;

            signVerified = AlipaySignature.rsaCheckV1(params,alipaypublicKey,charset,sign_type);


            if(signVerified){
                // TODO 验签成功后

                 /*// 另起线程处理业务
                        executorService.execute(new Runnable() {
                            @Override
                            public void run() {

                                wxOrderService.process(param);
                            }
                        });*/

                logger.info("####################验签成功！开始执行业务逻辑###########################");

                /**
                 * 兄弟下面这两个记得完善 回调的各个参数数据可以通过param.get方法中获取
                 */

                /**
                 * 还要判断支付宝反馈的支付金额和订单的金额是否一致（订单金额可以根据订单编号获取订单数据再拿到订单金额）
                 */

                /**
                 * 还要验证app_id是否为商户本身
                 */

                wxOrderService.process(param);

                System.out.println("success");

                return "success";

            }else{

                logger.info("####################验签失败！###########################");
                System.out.println("fail");
                return "fail";
            }

        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        return ResponseUtil.ok();
    }

    /**
     * 梨膏糖支付宝支付回调接口（暂时不用）
     * @param request
     * @return
     */
    @PostMapping("zfbpayligaotang")
    public Object zfbpayligaotang(HttpServletRequest request ) {


        //编码格式
        String charset="utf-8";
        //支付宝公钥
        String alipaypublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoTAdSr2AAjJpW723wKzfCjj1dhwSgOoES5kUz501QcfaQ4vz4CyxSCXVy3fq+odl1Hs2OImDEmhwGp/6P40I8gyn7GNraxi9QIbPa2NDpbZqXdPDHVgYeqz8ax/YthTMHjV+oHugS7YPpskyYDLVqE0APaRCkTLiERUszidlMGJC2YaT5wlTgdXBnGwvwscVt9sdETEVFa1chr7xj2bz89DFIEyJmlkCMDVLZE9Me1Y0VFKrC3z5Jn1yMdADOSc3Y8genMvJ3n1OOy7bLPcrj1vgG4cdZmQWMgnqRxCauQWkN2nFLZvJXdf+AWb/VRe2wX9JW9m4YZ9rOXhK7CMDxwIDAQAB";
        //签名方式
        String sign_type="RSA2";

        Map<String, String> paramss = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
        AlipayNotifyParam param = buildAlipayNotifyParam(paramss);
        logger.info("###############传给业务方法的对象"+param+"###############");





        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();

        Map requestParams = request.getParameterMap();

        logger.info("##############转化前的params"+requestParams+"###############");

        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        logger.info("##############转化后的params"+requestParams+"################");

        try {
            //异步验签：切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
            //公钥证书模式验签，alipayPublicCertPath是支付宝公钥证书引用路径地址，需在对应应用中下载
            //boolean signVerified= AlipaySignature.rsaCertCheckV1(params, alipayPublicCertPath, charset,sign_type);
            //普通公钥模式验签，切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
            /* 实际验证过程建议商户务必添加以下校验：
            1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
            2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
            3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
            4、验证app_id是否为该商户本身。
            */
            //验签方法
            boolean signVerified = false;

            signVerified = AlipaySignature.rsaCheckV1(params,alipaypublicKey,charset,sign_type);


            if(signVerified){
                // TODO 验签成功后

                 /*// 另起线程处理业务
                        executorService.execute(new Runnable() {
                            @Override
                            public void run() {

                                wxOrderService.process(param);
                            }
                        });*/

                logger.info("####################验签成功！开始执行业务逻辑###########################");

                /**
                 * 兄弟下面这两个记得完善 回调的各个参数数据可以通过param.get方法中获取
                 */

                /**
                 * 还要判断支付宝反馈的支付金额和订单的金额是否一致（订单金额可以根据订单编号获取订单数据再拿到订单金额）
                 */

                /**
                 * 还要验证app_id是否为商户本身
                 */

                wxOrderService.process(param);

                System.out.println("success");

                return "success";

            }else{

                logger.info("####################验签失败！###########################");
                System.out.println("fail");
                return "fail";
            }

        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        return ResponseUtil.ok();
    }


    // 将支付宝回调的request中的参数转换成Map
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {

        logger.info("####################convertRequestParamsToMap将支付宝回调的request中的参数转换成Map###########################");

        Map<String, String> retMap = new HashMap<String, String>();

        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;

            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.toString().substring(1));
            } else {
                retMap.put(name, "");
            }

        }

        return retMap;
    }



    private AlipayNotifyParam buildAlipayNotifyParam(Map<String, String> params) {
        String json = JSON.toJSONString(params);
        return JSON.parseObject(json, AlipayNotifyParam.class);
    }

    /**
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
     * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
     * 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
     *
     * @param params
     * @throws AlipayApiException
     */
    private void check(Map<String, String> params) throws AlipayApiException {

        /**
         * <pre>
         * 第一步:验证签名,签名通过后进行第二步
         * 第二步:按一下步骤进行验证
         * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
         * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
         * 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
         * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
         * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
         * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
         * </pre>
         *
         */

        AlipayConfig alipayConfig = new AlipayConfig();
        String outTradeNo = params.get("out_trade_no");

        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
        //Order order = getOrderByOutTradeNo(outTradeNo); // 这个方法自己实现

        LitemallOrder order = orderService.findBySn(outTradeNo);


        if (order == null) {
            throw new AlipayApiException("out_trade_no错误");
        }

        // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
        long total_amount = new BigDecimal(params.get("total_amount")).multiply(new BigDecimal(100)).longValue();

        if (total_amount != order.getActualPrice().longValue()) {

            throw new AlipayApiException("error total_amount");
        }

        // 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
        // 第三步可根据实际情况省略

        // 4、验证app_id是否为该商户本身。
        if (!params.get("app_id").equals(alipayConfig.getAppid())) {
            throw new AlipayApiException("app_id不一致");
        }

    }




    /**
     * 微信H5支付
     *
     * @param userId
     * @param body
     * @param request
     * @return
     */
    @PostMapping("h5pay")
    public Object h5pay(@LoginUser Integer userId, @RequestBody String body, HttpServletRequest request) {

        return wxOrderService.h5pay(userId, body, request);
    }

    /**
     * 微信付款成功或失败回调接口
     * <p>
     * TODO
     * 注意，这里pay-notify是示例地址，建议开发者应该设立一个隐蔽的回调地址
     *
     * @param request  请求内容
     * @param response 响应内容
     * @return 操作结果
     */
    @PostMapping("pay-notify")
    public Object payNotify(HttpServletRequest request, HttpServletResponse response) {
        logger.error("=======================微信支付回调开始==============");
        return wxOrderService.payNotifyLigaotang(request, response);
    }

    /**
     * 订单申请退款
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单退款操作结果
     */
    @PostMapping("refund")
    public Object refund(@LoginUser Integer userId, @RequestBody String body) {
        return wxOrderService.refund(userId, body);
    }

    /**
     * 确认收货
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单操作结果
     */
    @PostMapping("confirm")
    public Object confirm(@LoginUser Integer userId, @RequestBody String body) {
        return wxOrderService.confirm(userId, body);
    }

    /**
     * 删除订单
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单操作结果
     */
    @PostMapping("delete")
    public Object delete(@LoginUser Integer userId, @RequestBody String body) {
        return wxOrderService.delete(userId, body);
    }

    /**
     * 待评价订单商品信息
     *
     * @param userId 用户ID
     * @param ogid   订单商品ID
     * @return 待评价订单商品信息
     */
    @GetMapping("goods")
    public Object goods(@LoginUser Integer userId,
                        @NotNull Integer ogid) {
        return wxOrderService.goods(userId, ogid);
    }

    /**
     * 评价订单商品
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单操作结果
     */
    @PostMapping("comment")
    public Object comment(@LoginUser Integer userId, @RequestBody String body) {
        return wxOrderService.comment(userId, body);
    }



    /********************************测试接口********************************/
    @PostMapping("log")
    public Object moneyLog(@RequestParam Double pay,
                           @RequestParam Double income,
                           @RequestParam String remarks,
                           @RequestParam int userId,
                           @RequestParam String type) {

        int result = litemallMoneyLogService.insertMoney(pay,income,remarks,userId,type,0,0.00,0);

        return  result>0? ResponseUtil.ok():ResponseUtil.fail();

    }




    // 消费券支付--积分支付
    @PostMapping("/payxfq")
    public Object PayByxiaofeiquan(@LoginUser Integer userId,@RequestParam int  orderid) {
        logger.info("积分支付，用户userId:" + userId + ",订单id：" + orderid);
        System.out.println("积分支付，用户userId:" + userId + ",订单id：" + orderid);
        LitemallOrder order=     orderService.findById(orderid);
        return  order==null?"订单不存在，请刷新重试！":xiaofeiquanPay.paybyxfq(order,userId);

    }
}